package com.boat.starter.web.config;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;

import com.boat.framework.base.setting.EnvProps;
import com.boat.framework.common.config.factory.YmlPropertySourceFactory;
import com.boat.framework.common.sequence.SequenceStore;
import com.boat.framework.common.spring.transaction.TrxTemplate;
import com.boat.framework.common.util.JsonUtils;
import com.boat.framework.common.util.SpringUtils;
import com.boat.starter.web.excepton.GlobalExceptionHandler;
import com.boat.starter.web.filter.LoggingFilter;
import com.boat.starter.web.filter.TrackidFilter;
import com.boat.starter.web.listener.StartupListener;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

/**
 * starter自动配置
 * 
 * @author 周江
 *
 */
@Slf4j
@Configuration
@PropertySource(value = "classpath:web-common.yml", factory = YmlPropertySourceFactory.class)
public class WebAutoConfiguration implements InitializingBean {

	static {
		// 应用完全基于轻舟构建
		EnvProps.instance().setBasedOnBoat(true);
	}

	/**
	 * 跟踪号
	 * 
	 * @return
	 */
	@Bean
	public FilterRegistrationBean trackidFilter() {
		FilterRegistrationBean registration = new FilterRegistrationBean();
		registration.setFilter(new TrackidFilter());
		registration.addUrlPatterns("/*");
		registration.setOrder(0);
		return registration;
	}

	@Bean
	public FilterRegistrationBean loggingFilter() {
		FilterRegistrationBean registration = new FilterRegistrationBean();
		registration.setFilter(new LoggingFilter());
		registration.addUrlPatterns("/*");
		registration.setOrder(1);
		return registration;
	}

	@Bean
	public StartupListener startupListener() {
		return new StartupListener();
	}

	@Bean
	public GlobalExceptionHandler globalExceptionHandler() {
		return new GlobalExceptionHandler();
	}

	@Bean
	@Primary
	@ConditionalOnMissingBean(ObjectMapper.class)
	public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
		return JsonUtils.getDefaultObjectMapper();
	}

	/** 基于DB的ID序列生成器 **/
	@Bean
	@ConditionalOnBean(DataSourceAutoConfiguration.class)
	public SequenceStore sequenceStore() {
		return new SequenceStore();
	}

	/** 使用线程上下文已有事务 **/
	@Bean(SpringUtils.REQUIRED_TRX_TEMPLATE_BEAN_NAME)
	@ConditionalOnBean(DataSourceAutoConfiguration.class)
	public TrxTemplate requiredTransactionTemplate(PlatformTransactionManager transactionManager) {
		return new TrxTemplate(transactionManager, TransactionDefinition.PROPAGATION_REQUIRED);
	}

	/** 总是创建新事务 **/
	@Bean(SpringUtils.REQUIRES_NEW_TRX_TEMPLATE_BEAN_NAME)
	@ConditionalOnBean(DataSourceAutoConfiguration.class)
	public TrxTemplate requiresNewTransactionTemplate(PlatformTransactionManager transactionManager) {
		return new TrxTemplate(transactionManager, TransactionDefinition.PROPAGATION_REQUIRES_NEW);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		log.info("boat-starter-web-boot加载成功");
	}
}
